package org.zjvis.datascience.web.controller;

import cn.hutool.core.util.ObjectUtil;
import cn.weiguangfu.swagger2.plus.annotation.ApiGroup;
import cn.weiguangfu.swagger2.plus.annotation.ApiPlus;
import cn.weiguangfu.swagger2.plus.enums.ApiExecutionEnum;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.mayabot.nlp.common.Maps;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.zjvis.datascience.common.annotation.DashboardAuth;
import org.zjvis.datascience.common.annotation.ProjectAuth;
import org.zjvis.datascience.common.annotation.ProjectRoleAuth;
import org.zjvis.datascience.common.dto.*;
import org.zjvis.datascience.common.enums.ProjectAuthEnum;
import org.zjvis.datascience.common.enums.ProjectRoleAuthEnum;
import org.zjvis.datascience.common.enums.TaskTypeEnum;
import org.zjvis.datascience.common.exception.AutoTriggerException;
import org.zjvis.datascience.common.exception.DataScienceException;
import org.zjvis.datascience.common.exception.SqlParserException;
import org.zjvis.datascience.common.exception.UnionStatementParserException;
import org.zjvis.datascience.common.formula.vo.FormulaHistoryVO;
import org.zjvis.datascience.common.formula.vo.FormulaRequestVO;
import org.zjvis.datascience.common.formula.vo.FormulaVO;
import org.zjvis.datascience.common.model.ApiResult;
import org.zjvis.datascience.common.model.ApiResultCode;
import org.zjvis.datascience.common.util.CollectionUtil;
import org.zjvis.datascience.common.util.JwtUtil;
import org.zjvis.datascience.common.util.task.TaskDTOUtil;
import org.zjvis.datascience.common.vo.DashboardVO;
import org.zjvis.datascience.common.vo.TaskVO;
import org.zjvis.datascience.common.vo.project.ProjectDatasetVO;
import org.zjvis.datascience.common.widget.dto.WidgetDTO;
import org.zjvis.datascience.common.widget.request.RelateWidgetRequestVO;
import org.zjvis.datascience.common.widget.request.RelateWidgetResultVO;
import org.zjvis.datascience.common.widget.vo.*;
import org.zjvis.datascience.service.*;
import org.zjvis.datascience.service.dag.DAGScheduler;
import org.zjvis.datascience.service.snapshot.DashboardSnapshotManagerService;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;

import static org.zjvis.datascience.common.constant.DatabaseConstant.GREEN_PLUM_DEFAULT_SCHEMA;
import static org.zjvis.datascience.common.widget.constant.WidgetJsonConstant.PUBLISHED_FLAG;

/**
 * @description 可视化接口 Controller
 * @date 2021-12-24
 */
@ApiPlus(value = true)
@RequestMapping("/widget")
@RestController
@Api(tags = "widget", description = "可视化接口")
@Validated
public class WidgetController {

    @Autowired
    private WidgetService widgetService;

    @Autowired
    private WidgetFavouriteService widgetFavouriteService;

    @Autowired
    private TaskService taskService;

    @Autowired
    private PipelineService pipelineService;

    @Autowired
    private UserProjectService userProjectService;

    @Autowired
    private DatasetProjectService datasetProjectService;

    @Autowired
    private DAGScheduler dagScheduler;

    @Autowired
    private ModelLocalService modelLocalService;
    @Autowired
    private DashboardSnapshotManagerService dashboardManagerService;
    @Lazy
    @Autowired
    private DashboardService dashboardService;

    private static final String OPERATOR_ADD = "add";

    private static final String OPERATOR_UPDATE = "update";

    private final static Logger logger = LoggerFactory.getLogger(WidgetController.class);

    @PostMapping(value = "/save")
    @ResponseBody
    @ApiOperation(value = "新增可视化", notes = "新增可视化")
    public ApiResult<Long> save(
            HttpServletRequest request,
            @RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid WidgetVO vo)
            throws ExecutionException {
        Long dashboardId = vo.getDashboardId();
        dashboardManagerService.initialization(request, dashboardId);
        Long userId = JwtUtil.getCurrentUserId();
        //dashboardId 为-1代表是 点击加号创建的， 否则拖拽生成的则隶属于这个画布 需要传入对应dashboardId
        //dashboardId 为 -2 代表 该dashboard 已经被下架，项目中如果有发布了的画板被下架，  只有下架后才能被删除
        WidgetDTO widget = vo.toWidget();
        widget.setGmtCreator(userId);
        widget.setGmtModifier(userId);
        Long id = widgetService.save(widget);
        return ApiResult.valueOf(id);
    }

    @PostMapping(value = "/batchSave")
    @ResponseBody
    @ApiOperation(value = "批量新增可视化", notes = "批量新增可视化")
    public ApiResult<List<Long>> batchSave(HttpServletRequest r, @RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) JSONObject params) {
        List<Long> widgetIds = Lists.newArrayList();
        List<WidgetVO> vos = params.getJSONArray("widgets").toJavaList(WidgetVO.class);
        vos.forEach(vo -> {
            WidgetDTO widget = vo.toWidget();
            widget.setGmtCreator(JwtUtil.getCurrentUserId());
            widget.setGmtModifier(JwtUtil.getCurrentUserId());
            widgetIds.add(widgetService.save(widget));
        });
        return ApiResult.valueOf(widgetIds);
    }

    @ApiGroup(groups = WidgetVO.PUBLISH.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/update")
    @ResponseBody
    @ApiOperation(value = "更新可视化", notes = "更新可视化")
    public ApiResult<Long> update(
            HttpServletRequest request,
            @DashboardAuth @RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid WidgetVO vo)
            throws ExecutionException {
        Long dashboardId = widgetService.queryById(vo.getId()).getDashboardId();
        dashboardManagerService.initialization(request, dashboardId);
        widgetService.update(vo.toWidget());
        return ApiResult.valueOf(vo.getId());
    }

    @PostMapping(value = "/batchUpdate")
    @ResponseBody
    @ApiOperation(value = "批量更新可视化", notes = "批量更新可视化")
    public ApiResult<List<Long>> batchUpdate(HttpServletRequest request,
                                             @RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) JSONObject params) {
        try {
            List<Long> ids = widgetService.batchUpdate(params.getJSONArray("widgets"));
            return ApiResult.valueOf(ids);
        } catch (Exception e) {
            logger.error("API /widget/batchUpdate failed, since {}", e.getMessage());
            return ApiResult.error(ApiResultCode.SYS_ERROR, e.getMessage());
        }
    }

    @PostMapping(value = "/copy")
    @ResponseBody
    @ApiOperation(value = "拷贝可视化", notes = "拷贝可视化")
    @Transactional
    public ApiResult<List<WidgetVO>> copy(
            HttpServletRequest request,
            @RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid WidgetCopyRequestVO vo)
            throws ExecutionException {
        Long dashboardId = widgetService.queryById(vo.getId()).getDashboardId();
        dashboardManagerService.initialization(request, dashboardId);
        List<WidgetVO> res = widgetService.copy(vo);
        return ApiResult.valueOf(res);
    }

    /**
     * 返回全部节点信息以及配置信息
     *
     * @param r
     * @return
     */
    @ApiGroup(groups = DashboardVO.publishCombo.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/queryByProject")
    @ResponseBody
    @ApiOperation(value = "查询可视化", notes = "根据projectId查询可视化")
    public ApiResult<List<PipelineWidgetVO>> queryByProject(HttpServletRequest r, @RequestBody @Valid @DashboardAuth DashboardVO vo) {
        List<PipelineWidgetVO> resultList = Lists.newArrayList();
        //查询项目中引入的dataset节点，及其可视化视图
        List<ProjectDatasetDTO> datasetDTOS = datasetProjectService.queryProjectDataset(vo.getProjectId(), null);
        PipelineWidgetVO datasetWidgetVO = new PipelineWidgetVO(GREEN_PLUM_DEFAULT_SCHEMA);
        List<WidgetPackageVO> datasetWidgets = Lists.newArrayList();
        for (ProjectDatasetDTO dto : datasetDTOS) {
            List<WidgetDTO> addedWidget = widgetService.queryTemplateByDatasetIdAndProjectId(dto.getId(), vo.getProjectId());
            List<WidgetVO> addWidgetVOs = addedWidget.stream().map(WidgetDTO::view).collect(Collectors.toList());
            addWidgetVOs.addAll(0, dto.toWidgets()); //将原始的数据图表置于首位
            datasetWidgets.add(new WidgetPackageVO(dto.getId(), dto.getDatasetName(), addWidgetVOs));
        }
        //TODO 添加协作pipeline的数据集
        datasetWidgetVO.setTaskWidgets(datasetWidgets);
        resultList.add(datasetWidgetVO);
        //查询pipeline中的全部节点，及其可视化视图 (因为发布后，可能会复制pipeline 造成节点信息不同)
        List<PipelineDTO> pipelineDTOS = pipelineService.queryByProject(vo.getProjectId());
        if (null != vo.getPipelineId()) {
            //发布状态
            for (PipelineDTO pipeline : pipelineDTOS) {
                if (pipeline.getId().equals(vo.getPipelineId())) {
                    PipelineWidgetVO pipelineWidgetGroup = wrapPipelineWidgetGroup(pipeline.getId(), pipeline.getName());
                    resultList.add(pipelineWidgetGroup);
                    break;
                }
            }
        } else {
            //编辑态
            for (PipelineDTO pipeline : pipelineDTOS) {
                JSONObject dataJson = JSONObject.parseObject(pipeline.getDataJson());
                if (!dataJson.containsKey(PUBLISHED_FLAG)) {
                    PipelineWidgetVO pipelineWidgetGroup = wrapPipelineWidgetGroup(pipeline.getId(), pipeline.getName());
                    resultList.add(pipelineWidgetGroup);
                }
            }
        }

        PipelineWidgetVO gisPipelineWidget = new PipelineWidgetVO();
        gisPipelineWidget.setGroupName("gis");
        List<WidgetPackageVO> widgetPackages = Lists.newArrayList();
        List<WidgetDTO> widgets = widgetService.queryGisByProjectId(vo.getProjectId());
        for (WidgetDTO widget : widgets) {
            List<WidgetVO> tmpWidgets = new ArrayList<>();
            tmpWidgets.add(widget.view());
            widgetPackages.add(new WidgetPackageVO(widget.getTid(), widget.getName(), tmpWidgets));
        }
        gisPipelineWidget.setTaskWidgets(widgetPackages);
        resultList.add(gisPipelineWidget);

        return ApiResult.valueOf(resultList);
    }

    @ApiGroup(groups = FormulaVO.CREATE.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/addFormula")
    @ResponseBody
    @ApiOperation(value = "执行公式", notes = "根据给定的公式计算值")
    public ApiResult<WidgetFormulaVO> addFormula(@RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid FormulaVO vo) {
        if (vo.getFormula().isEmpty()) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR, WidgetFormulaVO.fail("公式不能为空。"));
        }
        WidgetFormulaVO widgetFormulaVO = widgetService.addOrUpdateFormula(vo.toHistoryDTO(), OPERATOR_ADD);
        return ApiResult.valueOf(widgetFormulaVO);
    }

    @PostMapping(value = "/updateFormula")
    @ResponseBody
    @ApiOperation(value = "更新公式", notes = "更新公式内容和数据集")
    public ApiResult<WidgetFormulaVO> updateFormula(@RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid FormulaVO vo) {
        if (vo.getFormula().isEmpty()) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR, WidgetFormulaVO.fail("公式不能为空。"));
        }
        WidgetFormulaVO widgetFormulaVO = widgetService.addOrUpdateFormula(vo.toHistoryDTO(), OPERATOR_UPDATE);
        return ApiResult.valueOf(widgetFormulaVO);
    }

    @ApiGroup(groups = FormulaVO.DELETE.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/deleteFormula")
    @ResponseBody
    @ApiOperation(value = "删除公式")
    public ApiResult<WidgetFormulaVO> deleteFormula(@RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid FormulaVO vo) {
        WidgetFormulaVO widgetFormulaVO = widgetService.deleteFormula(vo.getFormulaId());
        return ApiResult.valueOf(widgetFormulaVO);
    }

    @PostMapping(value = "/queryFormulaList")
    @ResponseBody
    @ApiOperation(value = "查询公式", notes = "根据projectId查询公式")
    public ApiResult<FormulaHistoryVO> queryFormulasByProjectId(@RequestBody @ProjectAuth @Valid FormulaRequestVO vo) {
        return ApiResult.valueOf(widgetService.queryFormulasByProjectId(vo));
    }

    @ApiGroup(groups = WidgetVO.ID.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/queryById")
    @ResponseBody
    @ApiOperation(value = "查询可视化", notes = "根据id查询单个可视化")
    public ApiResult<WidgetVO> queryById(HttpServletRequest request, @RequestBody @Valid WidgetVO vo) {
        if (vo == null || vo.getId() == null) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        return ApiResult.valueOf(widgetService.queryById(vo.getId()).view());
    }

    @ApiGroup(groups = WidgetVO.ID.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/queryByTid")
    @ResponseBody
    @ApiOperation(value = "查询可视化", notes = "根据tid查询单个可视化")
    public ApiResult<Boolean> queryByTid(HttpServletRequest request, @RequestBody @Valid WidgetVO vo) {
        List<WidgetDTO> widgetDTOS = widgetService.queryByTid(vo.getTid());
        if (widgetDTOS.size() > 0) {
            return ApiResult.valueOf(true);
        } else {
            return ApiResult.valueOf(false);
        }
    }

    @PostMapping(value = "/queryByTaskId")
    @ResponseBody
    @ApiOperation(value = "查询可视化列表", notes = "根据taskId查询可视化列表")
    public ApiResult<List<WidgetVO>> queryByTaskId(HttpServletRequest r, @RequestBody @Valid WidgetVO vo) {
        if (vo == null || vo.getTid() == null || !"task".equals(vo.getType())) {
            return ApiResult.valueOf(ApiResultCode.PARAM_ERROR);
        }
        TaskDTO taskDTO = taskService.queryById(vo.getTid());
        if (null != taskDTO) {
            //校验用户是否有项目的读权限
            userProjectService.checkAuth(taskDTO.getProjectId(), ProjectAuthEnum.READ.getValue());
        }
        List<WidgetDTO> widgets = widgetService.queryTemplateByTaskId(vo.getTid());
        List<WidgetVO> result = widgets.stream().map(WidgetDTO::view).collect(Collectors.toList());
        return ApiResult.valueOf(result);
    }

    @ApiGroup(groups = WidgetVO.ID.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/deleteById")
    @Transactional
    @ResponseBody
    @ApiOperation(value = "删除可视化", notes = "根据id删除单个可视化")
    public ApiResult<Void> deleteById(
            HttpServletRequest r,
            @RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid WidgetVO vo
    ) throws ExecutionException {
        Long id = vo.getId();
        if (widgetFavouriteService.queryById(id) != null) {
            widgetFavouriteService.deleteWidget(id);
        }
        Long dashboardId = widgetService.queryById(vo.getId()).getDashboardId();
        dashboardManagerService.initialization(r, dashboardId);
        widgetService.deleteById(id);
        //TODO 如果被删除的是关联图表 需要更新parent
        return ApiResult.valueOf(ApiResultCode.SUCCESS);
    }

    @ApiGroup(groups = WidgetVO.TID.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/deleteByTaskIds")
    @Transactional
    @ResponseBody
    @ApiOperation(value = "删除依赖某个Task可视化组件", notes = "根据TaskIds删除数个可视化")
    public ApiResult<Void> deleteByTaskId(HttpServletRequest r, @RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid WidgetVO vo) {
        List<Long> widgetIds = widgetService.listUsedWidgetsByTaskIds(vo.getTids()).stream()
                .map(WidgetDTO::getId).collect(Collectors.toList());
        widgetIds.stream().forEach(widgetId -> {
            widgetFavouriteService.deleteWidget(widgetId);
            widgetService.deleteById(widgetId);
        });
        //跟这个项目关联的所有dashboard layout 需要更新
        List<DashboardDTO> dashboardDTOS = dashboardService.queryByProjectId2(vo.getProjectId());
        dashboardDTOS.stream().forEach(dashboardDTO -> {
            dashboardService.removeWidgetByWidgetIds(dashboardDTO, widgetIds);
        });
        return ApiResult.valueOf(ApiResultCode.SUCCESS);
    }

    @ApiGroup(groups = WidgetVO.IDs.class, requestExecution = ApiExecutionEnum.INCLUDE)
    @PostMapping(value = "/batchDeleteByIds")
    @Transactional
    @ResponseBody
    @ApiOperation(value = "批量删除删除可视化", notes = "批量删除多个可视化")
    public ApiResult<Void> batchDeleteByIds(HttpServletRequest r, @RequestBody @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) @Valid WidgetVO vo) {
        if (ObjectUtil.isNotEmpty(vo.getWidgetIds())) {
            widgetFavouriteService.deleteWidgets(vo.getWidgetIds());
            widgetService.deleteByIds(null, vo.getWidgetIds());
        }

        return ApiResult.valueOf(ApiResultCode.SUCCESS);
    }

    @PostMapping(value = "/getGlobalWidgets")
    @ResponseBody
    @ApiOperation(value = "获取数据视图中收藏的可视化图表列表", notes = "获取数据视图中收藏的可视化图表列表")
    public ApiResult<JSONObject> getGlobalWidgets(HttpServletRequest request,
                                                  @ProjectAuth(auth = ProjectAuthEnum.READ) @RequestBody @Valid WidgetPageVO vo) {
        return ApiResult.valueOf(widgetService.getGlobalWidgets(vo));
    }


    @PostMapping(value = "/getRelateWidgets")
    @ResponseBody
    @ApiOperation(value = "获取相关图表列表", notes = "获取相关图表列表")
    public ApiResult<RelateWidgetResultVO> getRelateWidgets(HttpServletRequest request, @ProjectAuth(auth = ProjectAuthEnum.READ) @RequestBody @Valid RelateWidgetRequestVO vo) {
        if (vo.getIsFilterWidget()) {
            //可视化构建-筛选器控件 本身不提供渲染 但是可以驱动其他图表 重新渲染， 驱动关系由interactionJson 指定
            return ApiResult.valueOf(widgetService.getRelatedWidgetsWithinSpecificDataNode(vo));
        } else {
            return ApiResult.valueOf(widgetService.getRelateWidgetsInPipeline(vo));
        }
    }

    @PostMapping(value = "/datasets/queryAllDataset")
    @ApiOperation(value = "在系统构建中，加载或检索项目数据源")
    public ApiResult<Object> queryAllDataset(@RequestBody @DashboardAuth ProjectDatasetVO vo) {
        Object obj = datasetProjectService.queryAllDataset(vo.getProjectId(), vo.getPipelineId(), vo.getDatasetName());
        return ApiResult.valueOf(obj);
    }

    @PostMapping(value = "/execute")
    @ResponseBody
    @ApiOperation(value = "图表触发执行", notes = "图表触发执行单个任务节点")
    public ApiResult<List<Long>> execute(HttpServletRequest r, @RequestBody @DashboardAuth @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) JSONObject params) {
        //TODO 触发执行  前端也需要添加一个projectId
        Long taskId = pipelineService.traceMostHeadTask(params.getString("taskId"));
        List<Long> sessionIds = Lists.newArrayList();
        sessionIds.add(dagScheduler.triggerFullDose(params.getLong("id"), taskId, false));
        return ApiResult.valueOf(sessionIds);
    }

    @PostMapping(value = "/stop")
    @ApiOperation(value = "停止数据流图", notes = "停止单个数据流图")
    public ApiResult<String> stop(@RequestBody @DashboardAuth @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) JSONObject params) {
        //TODO 触发执行  前端也需要添加一个projectId
        try {
            for (String sessionId : params.getString("sessionId").split(",")) {
                dagScheduler.stopPipeline(Long.parseLong(sessionId));
            }
        } catch (DataScienceException e) {
            return ApiResult.valueOf(ApiResultCode.PIPELINE_STOP_ERROR, e.getMessage());
        }
        return ApiResult.valueOf(ApiResultCode.SUCCESS, "停止pipeline成功");
    }

    @PostMapping(value = "/simpleUpdate")
    @ResponseBody
    @Transactional
    @ApiOperation(value = "更新算子", notes = "更新算子")
    public ApiResult<Long> simpleUpdate(HttpServletRequest r, @RequestBody @DashboardAuth @ProjectRoleAuth(role = ProjectRoleAuthEnum.DEVELOPER) TaskVO vo) {
        //TODO 触发执行  前端也需要添加一个projectId
        if (vo.getUserId() == null) {
            vo.setUserId(JwtUtil.getCurrentUserId());
        }

        TaskDTO oldTask = taskService.queryById(vo.getId());
        TaskDTO dto = new TaskDTO();
        boolean updateX = false;
        //TODO 移进simpleUpdate 里去
        //update feature_cols as X for prediction ONLY FOR MODEL NODE
        if (vo.getType() != null && vo.getType() == TaskTypeEnum.TASK_TYPE_MODEL.getVal()) {
            try {
                String X = vo.getData().getString("feature_col");
                if (!X.equals("") && !X.equals(null)) {
                    updateX = true;
                }
            } catch (Exception e) {
                logger.error("API /task/simpleUpdate failed, since {}", e.getMessage());
                updateX = false;
            }
            if (updateX) {
                String X = vo.getData().getString("feature_col");
                TaskDTO task = oldTask;
                JSONObject dataJson = JSONObject.parseObject(task.getDataJson());
                dataJson.put("feature_X", X);
                String dataString = String.valueOf(dataJson);
                task.setDataJson(dataString);
                if (vo.getName() != null && vo.getName() != "") {
                    task.setName(vo.getName());
                }
                String childId = vo.getChildId();
                if (childId != null) {
                    task.setChildId(childId);
                }
                String parentId = vo.getParentId();
                if (parentId != null && parentId != "") {
                    task.setParentId(parentId);
                }
                dto = task;
            }
        }
        if (!updateX) {
            dto = vo.toTask();
        }
        if (vo.getType() != null && (vo.getType() == TaskTypeEnum.TASK_TYPE_ALGOPY.getVal() ||
                vo.getType() == TaskTypeEnum.TASK_TYPE_JLAB.getVal() ||
                vo.getType() == TaskTypeEnum.TASK_TYPE_AM.getVal()) ||
                vo.getType() == TaskTypeEnum.TASK_TYPE_JLHUB.getVal()) {
            TaskDTO task = oldTask;
            //todo
            if (task != null) {
                JSONObject newformData = vo.getData();
                JSONObject oldDataJson = JSONObject.parseObject(oldTask.getDataJson());
                JSONObject setParams = oldDataJson.getJSONArray("setParams").getJSONObject(0);
                JSONObject oldFormData = setParams.getJSONObject("formData");
                for (String key : newformData.keySet()) {
                    oldFormData.put(key, newformData.get(key));
                }
                task.setDataJson(oldDataJson.toString());

                String childId = vo.getChildId();
                if (childId != null) {
                    task.setChildId(childId);
                }
                String parentId = vo.getParentId();
                if (parentId != null && parentId != "") {
                    task.setParentId(parentId);
                }
                dto = task;
            }
        }

        List<ApiResultCode> errorCode = new ArrayList<>();
        if (!taskService.simpleUpdate(dto, errorCode, r)) {
            if (dto.getException() != null) {
                logger.error("API /task/simpleUpdate failed, since {}",
                        dto.getException().getMessage());
                if (dto.getException() instanceof UnionStatementParserException) {
                    return new ApiResult(ApiResultCode.UNION_TYPE_UNMATCHED, dto.getException().getMessage());
                } else if (dto.getException() instanceof SqlParserException) {
                    return new ApiResult(ApiResultCode.SQL_NOT_SUPPORT, dto.getException().getMessage());
                } else if (dto.getException() instanceof NullPointerException) {
                    return ApiResult.valueOf(ApiResultCode.DATA_NULL, null, "系统找不到对应的数据表！");
                } else {
                    return new ApiResult(ApiResultCode.SYS_ERROR, dto.getException().getMessage());
                }
            }
            logger.error("API /task/simpleUpdate failed, since {}", "更新失败");
            if (errorCode.size() > 0) {
                return ApiResult.valueOf(errorCode.get(0));
            } else {
                return new ApiResult(ApiResultCode.SYS_ERROR, "参数更新失败，请稍后重试");
            }
        }
        if (dto.getException() != null) {
            if (dto.getException() instanceof AutoTriggerException) {
                //针对 连线中间添加 JOIN/UNION/SQL节点
                return new ApiResult(ApiResultCode.AUTO_TRIGGER_FAILED, dto.getException().getMessage());
            } else {
                return new ApiResult<Long>(ApiResultCode.SYS_ERROR, dto.getException().getMessage());
            }
        }
        taskService.updateTaskName(dto, "update");
        taskService.updateTaskNode(dto.getPipelineId(), dto, "update");
        return ApiResult.valueOf(vo.getId());
    }

    /**
     * 包装生成PipelineWidgetVO
     *
     * @param pipelineId
     * @param pipelineName
     * @return
     */
    private PipelineWidgetVO wrapPipelineWidgetGroup(Long pipelineId, String pipelineName) {
        PipelineWidgetVO pw = new PipelineWidgetVO();
        pw.setPipelineId(pipelineId);
        pw.setGroupName(pipelineName);
        List<WidgetPackageVO> pipelineWidgets = Lists.newArrayList();
        List<TaskDTO> taskDTOS = taskService.queryByPipeline(pipelineId);

        if (CollectionUtil.isNotEmpty(taskDTOS)) {

            List<Long> taskIds = taskDTOS.stream().map(TaskDTO::getId).collect(Collectors.toList());

            List<WidgetDTO> templates = widgetService.queryTemplateByTaskIds(taskIds);
            HashMap<Long, List<WidgetDTO>> map = Maps.newHashMap();
            for (WidgetDTO widgetDTO : templates) {
                map.putIfAbsent(widgetDTO.getTid(), Lists.newArrayList());
                List<WidgetDTO> temp = map.get(widgetDTO.getTid());
                temp.add(widgetDTO);
                map.put(widgetDTO.getTid(), temp);
            }

            for (TaskDTO task : taskDTOS) {
                List<WidgetVO> tempVOS = task.toWidgets().stream().map(WidgetDTO::view)
                        .collect(Collectors.toList());

                Boolean flag = false;
                if (task.isThisTypeNode(TaskTypeEnum.TASK_TYPE_AM)) {
                    Long modelId = Long.valueOf(TaskDTOUtil.getValueByKey("modelId", task).toString());
                    ModelLocalDTO modelLocalDTO = modelLocalService.queryById(modelId);
                    if (modelLocalDTO != null) {
                        JSONObject config = JSONObject.parseObject(modelLocalDTO.getConfig());
                        if (config != null && config.getString("has_tmp_result") != null && config.getBoolean("has_tmp_result")) {
                            flag = true;
                        }
                    }
                }
                if (map.containsKey(task.getId())) {
                    tempVOS.addAll(map.get(task.getId()).stream().map(WidgetDTO::view)
                            .collect(Collectors.toList()));
                }
                pipelineWidgets.add(new WidgetPackageVO(task.getId(), task.getName(), flag, tempVOS));
            }
        }
        pw.setTaskWidgets(pipelineWidgets);
        return pw;
    }


}

